package com.clouddong.exterapi.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.clouddong.exterapi.ProbeConstant;
import com.clouddong.exterapi.po.ProbeListTablePo;
import com.clouddong.exterapi.po.ProbeTaskXmlPingJoinPo;
import com.clouddong.exterapi.po.ProbeXmlPingListJoinPo;
import com.clouddong.exterapi.service.ProbeListServiceI;
import com.clouddong.exterapi.service.ProbeOperationServiceI;
import com.clouddong.exterapi.service.impl.ProbeClientServiceImpl;
import com.clouddong.exterapi.service.impl.ProbeOperationServiceImpl;
import com.clouddong.exterapi.util.Tools;
import com.clouddong.exterapi.vo.ProbeListTableVo;
import com.github.pagehelper.PageInfo;
import com.util.DateUtil;

import net.sf.json.JSONObject;

@Controller
@RequestMapping(value="probeOperationApi")
@CrossOrigin(origins="*")//解决跨域问题
/**
<blockquote>
<h1>运维接口的的控制器类</h1>
* @author lpr
* @version 1.0.0
* @date [2018年7月17日 下午1:23:25]
*/
public class ProbeOperationController
{
	@Resource(name="probeOperationServiceImpl")
	private ProbeOperationServiceI probeOperationServiceI;
	@Resource(name="probelistService")
	private ProbeListServiceI probeListServiceI;
	
	//private final int intervalTime=5;//间隔的单位秒
	// final int overTime = 300;//超时的时间单位秒
	/**
	 * Log4j日志记录
	 */
	private final static Logger logger = LoggerFactory.getLogger(ProbeOperationController.class);
	/**
	<blockquote>
	<h1>查询可用探针列表的省份，地市，id</h1>
	* @version 1.0.0
	* @return 包含省份地市信息的List
	 */
	@RequestMapping(value="getGoodProbeArea",method= {RequestMethod.POST},produces="application/json;charset=utf-8")
	@ResponseBody
	public List<Map<String, Object>> getOperProvinceArea() throws Exception
	{
		 System.out.println("-----------进入了getOperProvinceArea方法---------");
		//定义最终返回的LIst
	  List<Map<String, Object>> retList=new ArrayList<>();
	  try
	  {
		//获得返回的List<ProbeListTablePo>类型的数据
		retList=probeOperationServiceI.getFinalDataByField(getProvinceAreaField());
			
	  }catch (Exception e)
	  {
		  e.printStackTrace();
	  }	
	  return retList;
	}
	/**
	<blockquote>
	<h1>根据任务ID查询省份地市对应的Ping值</h1>
	* @version 1.0.0
	* @param task_id - 任务ID
	* @param proPingRule - 查询规则
	* @return
	*/
	@RequestMapping(value="getProvCityPingQuery",method= {RequestMethod.POST},produces="application/json;charset=utf-8")
	@ResponseBody
	public JSONObject getProvCityPingQuery(
			@RequestParam(name="task_id",required=false)String taskId,
			@RequestParam(name="proPingRule",required=false)String proPingRule)
	{
	  System.out.println("-----------进入了getProvCityPingQuery方法---------");
	  //定义最终返回的JSON
	  JSONObject retJson=new JSONObject();
	  try{
		String[] verInfo=isAttributeLeg(new Object[]{taskId,proPingRule});
		if(!Boolean.parseBoolean(verInfo[0]))
		{//判断产数是否合法,不合法就返回对应的JSON
			retJson.put("status_code", 3);
			retJson.put("describe", verInfo[1]);
			return retJson;
		}
		if(!taskTypeIdCorTaskTypeName().containsKey(Integer.parseInt(proPingRule)))
		{//判断传入的proPingRule是否存在
			retJson.put("status_code", 2);
			retJson.put("describe", "Rule of judgment that does not exist");
			return retJson;
		}
		if(true)
		{
		  /*Long indexTime=(long)0;//时间累加值
		   Boolean result = false;//判断是否还需要循环
		   while(!result)
		   {//循环执行查询*/			
			//获取list表下的所有数据
			List<ProbeListTablePo> listTableDataList=probeOperationServiceI.getDataSourceIsOperQuery(new ProbeListTableVo());
			//判断list表下是否有数据
			if(listTableDataList.size()>0)
			{
				//获取数据源
				List<ProbeXmlPingListJoinPo> dataList= probeOperationServiceI.getDataSourceIsOperPing(taskId);
				//判断数据源是否有数据
				if(dataList.size()>0){
				//List<ProbeJointTablePo> dataList = probeOperationServiceI.getDataSourceIsOperTask(task_id);
				//将数据传给JSON封装类
				Map<String,List<List<Map<String,Object>>>> retMap=probeOperationServiceI.getFinalDataIsOperPingMap(dataList,proPingRule);
				System.out.println(retMap.size());
				//判断并更改省份的Ping码
				retMap=isProvincePingExi(retMap,proPingRule);
				//封装数据
				retJson=JSONObject.fromObject(retMap);
				//result=true;
				}else {
					retJson.put("mssage", "wait for");
				}
			}else {
				retJson.put("mssage", "无可用探针");
			}
			/*if(!result)
			{//是否需要线程睡眠
				indexTime+=intervalTime*1000;
				System.out.println("线程名称："+Thread.currentThread().getName());
				Thread.currentThread().sleep(intervalTime*1000);
			}
			if(indexTime>=overTime*1000)
			{//判断是否超时
				retJson.clear();
		 		retJson.put("mssage", "查询超时");
				break;
			}
		  }*/
		}
	  }
	  catch (Exception e)
	  {
		e.printStackTrace();
	  }
	  return retJson;
	}
	/**
	<blockquote>
	<h1>根据任务ID查询省份地市对应的Ping值</h1>
	* @version 1.0.0
	* @param task_id - 任务ID
	* @param proPingRule - 查询规则
	* @return
	*/
	@RequestMapping(value="getProvCityPingTable",method= {RequestMethod.POST,RequestMethod.GET},produces="application/json;charset=utf-8")
	@ResponseBody
	public JSONObject getProvCityPingTable(
			@RequestParam(name="draw",required=false)Integer draw,
			@RequestParam(name="start",required=false)Integer pageCount, 
			@RequestParam(name="length",required=false)Integer pageSize,
			@RequestParam(name="order[0][column]",required=false)Integer order,
			@RequestParam(name="order[0][dir]",required=false)String orderDir,
			@RequestParam(name="task_id",required=false)String taskId,
			@RequestParam(name="proPingRule",required=false)String proPingRule,
			@RequestParam(name="provinceName",required=false)String provinceName)
	{
		  System.out.println("-----------进入了getProvCityPingTable方法---------");
		  //定义最终返回的JSON
		  JSONObject retJson=new JSONObject();
		  try{
			if(true)
			{
				//获取数据源
				PageInfo<ProbeXmlPingListJoinPo> pageDataList = probeOperationServiceI.getPageDataSourceIsOperPingMap(
								taskId, provinceName, pageCount, pageSize, order == null? null:order+1, orderDir);
				//将数据传给JSON封装类
				List<List<String>> retList=probeOperationServiceI.getFinalDataIsOperPingTable(pageDataList.getList(),proPingRule);
				//封装最终数据
				retJson=JSONObject.fromObject(
						ProbeClientServiceImpl.getFinalPageDataJson(draw, pageDataList.getTotal(),pageDataList.getTotal(),retList));
			}
		  }catch (Exception e) 
		  {
			  e.printStackTrace();
			  //异常发生时将不再返回空数据导致表格无法识别而报错而是返回表格可以识别的JSON但里边没数据
			  retJson=JSONObject.fromObject(
						ProbeClientServiceImpl.getFinalPageDataJson(
								draw,
								0L,0L,new ArrayList<Object>() ));
		  }
		  return retJson;
		
	}
	/**
	<blockquote>
	<h1>查询可用探针列表的数据并以分页形式返回</h1>
	* @version 1.0.0
	* @param pageNum - 当前页
	* @param pageSize - 每页大小
	* @param probeVo - ProbeListTableVo对象
	* @return 分页后的JSON数据
	 */
	@RequestMapping(value="getGoodProbeQuery",method= {RequestMethod.POST,RequestMethod.GET},produces="application/json;charset=utf-8")
	@ResponseBody
	public JSONObject getOperationQuery(
			@RequestParam(name="draw",required=false)Integer draw,
			@RequestParam(name="start",required=false)Integer pageCount, 
			@RequestParam(name="length",required=false)Integer pageSize,
			@RequestParam(name="order[0][column]",required=false)Integer order,
			@RequestParam(name="order[0][dir]",required=false)String orderDir,
			@ModelAttribute(value="probeListTableVo")ProbeListTableVo probeListTableVo)
	{
		System.out.println("-----------进入了getOperationQuery方法---------");
		// 定义最终返回的List
		JSONObject retJson = new JSONObject();
		try
		{
			//获得分页后的数据源
			PageInfo<ProbeListTablePo> pageDataList= probeOperationServiceI.getPageDataSourceIsOperQuery
					(probeListTableVo, pageCount, pageSize,order==null?null:order+1,orderDir);
			//将分页后的数据封装为指定格式
			List<List<String>>  dataList=probeOperationServiceI.getFinalDataIsOperQuery(pageDataList.getList());
			//封装最终的JSON
			retJson=JSONObject.fromObject(ProbeClientServiceImpl.getFinalPageDataJson(draw,pageDataList.getTotal(),pageDataList.getTotal(), dataList));
		} catch (Exception e)
		{
			e.printStackTrace();
		}
		return retJson;
	}
	/**
	<blockquote>
	<h1>根据任务ID查询省份地市对应的Ping值</h1>
	* @version 1.0.0
	* @param task_id - 任务ID
	* @param proPingRule - 查询规则
	* @return
	*/
	@RequestMapping(value="getTaskListQuery",method= {RequestMethod.POST,RequestMethod.GET},produces="application/json;charset=utf-8")
	@ResponseBody
	public JSONObject getTaskListQuery(
			@RequestParam(name="draw",required=false)Integer draw,
			@RequestParam(name="start",required=false)Integer pageCount, 
			@RequestParam(name="length",required=false)Integer pageSize,
			@RequestParam(name="order[0][column]",required=false)Integer order,
			@RequestParam(name="order[0][dir]",required=false)String orderDir,
			@RequestParam(name="task_id",required=false)String taskId,
			@RequestParam(name = "type_id", required = false) Integer typeId,
			@RequestParam(name = "createtime", required = false) String createtime,
			@RequestParam(name = "endtime", required = false) String endtime,
			@RequestParam(name = "host_ip", required = false) String hostIp){
		System.out.println("-----------进入了getTaskListQuery方法---------");
		// 定义最终返回的List
		JSONObject retJson = new JSONObject();
		try
		{
			if(typeId!=null&&!taskTypeIdCorTaskTypeName().containsKey(typeId))
			{//判断传入的type_id是否存在
				retJson.put("status_code", 2);
				retJson.put("describe", "Type_id that does not exist");
				return retJson;
			}
			//获得分页后的数据源
			PageInfo<ProbeTaskXmlPingJoinPo> pageDataList= probeOperationServiceI.getPageDataSourceIsOperTask
					(taskId,isTypeIdIsTask(typeId),
					createtime!=null&&!"".equals(createtime)?DateUtil.getDateStrIsStrDate(createtime, "yyyy-MM-dd HH:mm"):null,
					endtime!=null&&!"".equals(endtime)?DateUtil.getDateStrIsStrDate(endtime, "yyyy-MM-dd HH:mm"):null,
					hostIp,pageCount, pageSize,order==null?null:order,orderDir);
			
			/*List<ProbeTaskXmlPingJoinPo> aa= probeOperationServiceI.getDataSourceIsOperTask(task_id,isTypeIdIsTask(type_id),
					createtime!=null&&!createtime.equals("")?DateUtil.getDateStrIsStrDate(createtime, "yyyy-MM-dd HH:mm"):null,
					endtime!=null&&!endtime.equals("")?DateUtil.getDateStrIsStrDate(endtime, "yyyy-MM-dd HH:mm"):null,
					host_ip,order==null?null:order,orderDir);*/
			//将分页后的数据封装为指定格式
			List<List<String>>  dataList=probeOperationServiceI.getFinalDataIsOperTask(pageDataList.getList());
			//封装最终的JSON
			retJson=JSONObject.fromObject(ProbeClientServiceImpl.getFinalPageDataJson(draw,pageDataList.getTotal(),pageDataList.getTotal(), dataList));
		} catch (Exception e)
		{
			e.printStackTrace();
			//异常发生时将不再返回空数据导致表格无法识别而报错而是返回表格可以识别的JSON但里边没数据
			retJson=JSONObject.fromObject(
					ProbeClientServiceImpl.getFinalPageDataJson(draw,0L,0L,new ArrayList<Object>()));
		}
		return retJson;
	}
	/**
	<blockquote>
	<h1>封装查询表要返回的字段</h1>
	* @version 1.0.0
	* @return
	 */
	private List<String> getProvinceAreaField(){
		List<String> retList=new ArrayList<>();
		retList.add("probe_id");
		retList.add("probe_province");
		retList.add("probe_city");
		return retList;
	}
	/**
	<blockquote>
	<h1>根据自定义的规则拿地市的Ping码去判断省份的Ping码</h1>
	* @version 1.0.0
	* @param pJson - 省份的List<&JSONObject>的数据
	* @param pPingCodeKey - 要判断的省份Ping码所对应的Key，用来获取当前省份Ping码
	* @param cityPingCode - 地市Ping码
	* @return - JSON格式的经过判断的JSON
	 */
	private Map<String,List<List<Map<String,Object>>>> isProvincePingExi(Map<String,List<List<Map<String,Object>>>> retMap,String mode)
		throws Exception{
		String typeIdWall="0";
		if(typeIdWall.equals(mode))
		{//封堵方式
		    return getProRuleIsWall(retMap);
		}
		if(ProbeConstant.TYPE_ID_PING.equals(mode))
		{//Ping方式
			return getProRuleIsPing(retMap);
		}
		return retMap;
	}
	/**
	<blockquote>
	<h1>省份Ping码规则——封堵</h1>
	* @version 1.0.0
	* @param retJson - 最终返回的JSON
	* @return
	 */
	private Map<String,List<List<Map<String,Object>>>> getProRuleIsWall(Map<String,List<List<Map<String,Object>>>> dataMap)
		throws Exception{
	    Map<String,List<List<Map<String,Object>>>> retMap=dataMap;
		// 定义地市不通代表的Code
		Integer cityNoPingCode=1;
		// 定义一个迭代器用来遍历retJson
		Iterator<String> keyIterator = retMap.keySet().iterator();
		List<List<Map<String,Object>>> dataObjAll;
		List<Map<String,Object>> dataJsonAll;
		while (keyIterator.hasNext())
		{// 遍历retJson的key
			// 定义一个计数器，计算地市不通出现的次数
			Integer cityNoPingIndex = 0;
			
			// 获得json的key
			String key = keyIterator.next();
			// 根据省份获得isProPingJson中对应的类型为List<Object>的地市信息
			dataObjAll = retMap.get(key);
			// 定义一个初始为0的省份PingCode
			Integer proPingCode = 0;
			// 获取该List<List<Map<String,Object>>>的第二位的地市信息
			dataJsonAll = dataObjAll.get(1);
			for (int i = 0, len = dataJsonAll.size(); i < len; i++)
			{
				if(cityNoPingCode.equals(Integer.parseInt(dataJsonAll.get(i).get(ProbeOperationServiceImpl.CITY_PINGCODE_KEY).toString())))
				{//判断地市不通出现的次数
				    cityNoPingIndex++;
				}
			}
			if ((cityNoPingIndex * 1.0) >= dataJsonAll.size() / 2.0)
			{// 判断当地市不通出现的次数是否大于等于总次数的一半
				// 不通
				proPingCode = 1;
			}else
			{
				// 通
				proPingCode = 0;
			}
			// 修改对应的省份Ping码
			retMap = setProvincePingCode(retMap, key, ProbeOperationServiceImpl.PRO_PINGCODE_KEY, proPingCode);
		}
		return retMap;
	}
	/**
	<blockquote>
	<h1>省份Ping码规则——Ping</h1>
	* @version 1.0.0
	* @param retJson - 最终返回的JSON
	* @return
	 */
	private Map<String,List<List<Map<String,Object>>>> getProRuleIsPing(Map<String,List<List<Map<String,Object>>>> dataMap)
	    throws Exception{
	    Map<String,List<List<Map<String,Object>>>> retMap=dataMap;
		// 定义当出现不同的地市码时省份对应的Ping码
		Integer proChangePingCode=2;
		// 定义一个迭代器用来遍历retJson
		Iterator<String> keyIterator = retMap.keySet().iterator();
		List<List<Map<String,Object>>> dataObjAll;
		List<Map<String,Object>> dataJsonAll;
		while (keyIterator.hasNext()){// 遍历retJson的key
			// 获得省份key
			String key = keyIterator.next();
			// 根据省份获得isProPingJson中对应的类型为List<Object>的地市信息
			dataObjAll = retMap.get(key);
			// 获取该List<Object>的最后一位类型为List<JSONObject>的地市信息
			dataJsonAll = dataObjAll.get(1);
			for (int i = 0, len = dataJsonAll.size(); i < len; i++){
				if(i>0&&
				(Integer.parseInt(dataJsonAll.get(i).get(ProbeOperationServiceImpl.CITY_PINGCODE_KEY).toString())
				!=Integer.parseInt(dataJsonAll.get(i-1).get(ProbeOperationServiceImpl.CITY_PINGCODE_KEY).toString())
			    ))//判断当前位不为0且当前位的地市Ping码不等于上一位的地市Ping码
				{
					// 修改对应的省份Ping码
					retMap = setProvincePingCode(retMap, key,ProbeOperationServiceImpl.PRO_PINGCODE_KEY, proChangePingCode);
					break;
				}
			}
			
		}
		return retMap;
	}
	
	/**
	<blockquote>
	<h1>设置最终返回的JSON中的省份Ping码</h1>
	* @version 1.0.0
	* @param retJson - 最终返回的JSON
	* @param ProKey - 要修改的省份key
	* @param proPingCodeKey - 省份Ping码对应的Key
	* @param proPingCode - 要修改的省份Ping码
	* @return - 修改后的JSON
	 */
	private Map<String,List<List<Map<String,Object>>>> setProvincePingCode
	    (Map<String,List<List<Map<String,Object>>>> retMap,String proKey,String proPingCodeKey,Integer proPingCode) throws Exception{
		// 获得当前省份key对应的value
		List<List<Map<String,Object>>> dataObjAll=retMap.get(proKey);
		// 获取第一个元素，为省份信息
		List<Map<String,Object>> dataJsonAll= dataObjAll.get(0);
		// 获取第一个元素，为省份JSON
		Map<String,Object> proJson=dataJsonAll.get(0);
		// 修改对应的Ping码
		proJson.put(proPingCodeKey, proPingCode);
		// 逆向将修改完毕的元素放回
		dataJsonAll.set(0, proJson);
		dataObjAll.set(0, dataJsonAll);
		retMap.put(proKey, dataObjAll);
		return retMap;
	}
	/**
	<blockquote>
	<h1>判断传入的属性是否合法</h1>
	* @version 1.0.0
	* @param objAll - 传入的属性集合
	* @return String[]类型，0位为是否合法true或false，value为提示信息
	 */
	private String[] isAttributeLeg(Object[] objAll) throws Exception{
		String[] retStrAll=new String[]{"true",""};
		for(int i=0,len=objAll.length;i<len;i++)
		{
		  if(objAll[i]==null)
		  {
			retStrAll[0]="false";
			retStrAll[1]="Property cannot be null";
			return retStrAll; 
		  }
		  if(!Tools.isNumber(objAll[i].toString()))
		  {
			retStrAll[0]="false";
			retStrAll[1]=objAll[i].getClass().getName()+" Only for numbers";
			return retStrAll;
		  }
		}
		return retStrAll;
	}
	/**
	<blockquote>
	<h1>判断探针类型对应的实际类型</h1>
	* @version 1.0.0
	* @param type_id
	* @return
	 */
	private Integer isTypeIdIsTask(Integer typeId){
		if(typeId==null){return null;}
		Integer retInt=typeId;
		if(retInt.equals(0)){retInt=1;}
		return retInt;
	}
	/**
	<blockquote>
	<h1>探针类型ID和探针类型的对应关系</h1>
	* @version 1.0.0
	* @return
	*/
	private static Map<Integer, String> taskTypeIdCorTaskTypeName(){
		 Map<Integer, String> map=new HashMap<>(6);
		 map.put(0, ProbeConstant.TYPE_ID_PING);
		 map.put(1, ProbeConstant.TYPE_ID_PING);
		 map.put(2, ProbeConstant.TYPE_ID_HTTP);
		 map.put(3, ProbeConstant.TYPE_ID_FLASH);
		 map.put(4, ProbeConstant.TYPE_ID_DNS);
		 map.put(5, ProbeConstant.TYPE_ID_TRACE);
		 return map;
	}
}
